export function guid() {
  return "ss-s-s-s-sss".replace(/s/g, s4);
}

function s4() {
  return Math.floor((1 + Math.random()) * 0x10000)
    .toString(16)
    .substring(1);
}

export const omit = (obj, arr) =>
  Object.keys(obj)
    .filter(k => !arr.includes(k))
    .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});

const uniqueElementsBy = (arr, fn) => {
  return arr.reduce((acc, v) => {
    if (!acc.some(x => fn(v, x))) acc.push(v)
    return acc
  }, [])
}

export function unionObjArr(arr, keys) {
  return uniqueElementsBy(arr, (a, b) => {
    let isNeedFilter = keys.every(key => {
      return a[key] == b[key]
    })
    return isNeedFilter
  })
}

export const getObject = (from, ...selectors) =>
  [...selectors].map(s =>
    s
      .replace(/\[([^\[\]]*)\]/g, '.$1.')
      .split('.')
      .filter(t => t !== '')
      .reduce((prev, cur) => prev && prev[cur], from)
  );

export const getObjectFirst = (from, ...selectors) => {
  let ret = getObject(from, ...selectors)
  if (Array.isArray(ret)) {
    return ret[0]
  }
  return ret
}

/**
 * 用于从一个object上收集部分key
 *
 * @param obj
 * @param keys
 * @param iffun  过滤函数
 * @returns {Array}
 */
export let collectArr = function (obj, keys = [], iffun) {
  let ret = []
  keys.forEach(function (key) {
    if (iffun) {
      let _is = iffun(obj[key], key)
      if (_is) {
        ret.push(obj[key])
      }
    } else {
      ret.push(obj[key])
    }
  })
  return ret
}

export function isNull(value) {
  return (Object.prototype.toString.call(value) === '[object Null]')
}

export function isUndefined(value) {
  return typeof value === 'undefined'
}

export function calcTotal(args = []) {
  let r = 0
  args.forEach((item) => {
    let v = 0
    if (item) {
      v = parseInt(item)
      if (isNaN(v)) {
        v = 0
      }
    }
    r = r + v
  })
  return r
}

let simple_pick = (obj, arr) => {
  return arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
}

export let pick = simple_pick

export function merge(obj1, obj2) {
  let d = obj1
  for (let key in obj2) {
    if (typeof obj2[key] !== 'undefined') {
      d[key] = obj2[key]
    }
  }
  return d
}

export function newmerge(obj1, obj2) {
  let d = obj1
  for (let key in obj2) {
    if (typeof obj2[key] !== 'undefined' &&  obj2[key] !== null) {
      d[key] = obj2[key]
    }
  }
  return d
}

export function isNumeric(n) {
  return !isNaN(parseFloat(n)) && isFinite(n)
}

/**
 * format url
 *
 * @param url
 * @param args
 * @example
 *
 * formatUrl('/student/course/:uuid/intention/', {
 *   uuid: 1
 * })
 * @returns {*}
 */
export function _formatUrl(url, args = {}) {
  let a = url
  for (let k in args) {
    a = a.replace(new RegExp(`:(${k})+`, 'g'), args[k])
  }
  return a
}

export function formatUrl(url, args = {}, h = (v) => { return v  }) {
  return _formatUrl(h(url), args)
}

function nativePost(url, data, header, options = {}) {
  wx.request({
    url,
    method: 'POST',
    data: data,
    header: header,
    success(res) {
      if (options.success) {
        options.success(res)
      }
    },
    fail(e) {
      if (options.fail) {
        options.fail(e)
      }
    }
  })
}

export function getLastPage() {
  let pages = getCurrentPages()
  let lastPage = null
  if (pages && pages.length > 0) {
    lastPage = pages[pages.length - 1]
  }
}

export function encodeQueryData(data, encode = false) {
  let ret = []
  for (let d in data) {
    if (encode) {
      ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]))
    } else {
      ret.push(d + '=' + data[d])
    }
  }
  return ret.join('&')
}

export function decodeQueryData(str) {
  if (!str || str.length < 1) {
    return {}
  }
  var obj = str.split("&").reduce(function(prev, curr, i, arr) {
    var p = curr.split("=");
    prev[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
    return prev;
  }, {});
  return obj
}

export function getTaskId(url, params, headers) {
  return url + encodeQueryData(params)
}

export function isFunction(functionToCheck) {
  return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
}
